package com.cwx.mychat.utils.common;


import com.cwx.mychat.entity.dto.TokenUserInfoDto;
import com.cwx.mychat.entity.enums.UserContactStatusEnum;
import com.cwx.mychat.entity.enums.UserContactTypeEnum;
import com.cwx.mychat.entity.po.UserContact;
import com.cwx.mychat.entity.po.UserInfo;
import com.cwx.mychat.utils.jwt.JwtUtils;
import com.cwx.mychat.utils.stringUtils.StringUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.stringtemplate.v4.ST;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 作者： cwx
 * 时间： 2024/9/15 20:48
 * 版本： 1.0
 * 注释：
 */
@Slf4j
public class CommonUtil {


    private static final ObjectMapper objectMapper = new ObjectMapper();
    /**
     * 以JSON格式输出
     * @param response
     * @param responseMap
     */
    public static void responseOutWithJson(HttpServletResponse response, Map<String, Object> responseMap){

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try(PrintWriter out = response.getWriter()){
            String jsonResponse = objectMapper.writeValueAsString(responseMap);
            out.print(jsonResponse);
            out.flush();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    /**
     * 获取SpringSecurity上下文
     */
    public static TokenUserInfoDto getSecurityContext(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if(authentication != null && authentication.isAuthenticated()){
            Object details = authentication.getPrincipal();
            if(details instanceof TokenUserInfoDto){
                return (TokenUserInfoDto) details;
            }

        }
        throw new RuntimeException("无法获取SpringSecurity上下文");
    }

    /**
     * 解析并校验token出userId
     * @param token
     * @return
     */
    public static String checkToken(String token) {
        //检查Token是否过期
        String userId;
        boolean expired = JwtUtils.isExpired(token);
        if(expired){
            throw new RuntimeException("Token过期");
        }
        //解析jwt
        try {
            Jws<Claims> claimsJws = JwtUtils.parseJWT(token);
            Claims claims = claimsJws.getPayload();
            userId = claims.getSubject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("token非法");
        }
        return userId;
    }

    /**
     *
     * 获取两个两天用户的公共会话Id
     * @param userIds
     * @return
     */
    public static String getChatSessionIdUser(String[] userIds){
        Arrays.sort(userIds);
        return StringUtil.MD5(StringUtils.join(userIds));
    }

    /**
     * JSON字符串转Map
     * @param json
     * @return
     */
    public static Map convertJsonToMap(String json){
        try {
            return objectMapper.readValue(json, Map.class);
        }catch (Exception e){
            log.error("json字符串转换Map失败", e);
            return null;
        }
    }

    /**
     * JSON字符串转List
     * @param json
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> List<T> convertJsonToList(String json,Class<T> clazz){
        try{
            return objectMapper.readValue(json, new TypeReference<List<T>>() {});
        }catch (Exception e){
            log.error("json字符串转换List失败", e);
            return null;
        }
    }

    /**
     * 获取用户是否被拉黑
     * @param userContactList
     * @param userInfo
     * @return
     */
    public static String getBlock(List<UserContact> userContactList, UserInfo userInfo){
        for (UserContact usercontact :
                userContactList) {
            if(usercontact.getUserId().equals(userInfo.getUserId())
                    || usercontact.getContactId().equals(userInfo.getUserId())){
                //判断是userId还是contactId
                if(usercontact.getUserId().equals(userInfo.getUserId())){
                    //判断是userId拉黑还是contactId拉黑
                    if(usercontact.getStatus().equals(UserContactStatusEnum.BLOCKED.getStatus())){
                        return "你已拉黑该用户";
                    }
                    if(usercontact.getStatus().equals(UserContactStatusEnum.BE_BLOCKED.getStatus())){
                        return "";
                    }
                }else{
                    if(usercontact.getStatus().equals(UserContactStatusEnum.BLOCKED.getStatus())){
                        return "";
                    }
                    if(usercontact.getStatus().equals(UserContactStatusEnum.BE_BLOCKED.getStatus())){
                        return "你已拉黑该用户";
                    }
                }
            }
        }
        return null;
    }

    /**
     * Map转对象
     * @param map
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> T mapToObject(Map map, Class<T> clazz) throws Exception{
        // 获取构造函数
        Constructor<T> constructor = clazz.getDeclaredConstructor();
        T instance = constructor.newInstance();
        // 遍历类的字段
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();

            // 如果 Map 中包含对应的键，则进行赋值
            if (map.containsKey(fieldName)) {
                Object value = map.get(fieldName);
                if(value != null && !field.getType().isAssignableFrom(value.getClass())){
                    throw new RuntimeException(field.getName() + "类型不匹配, 需要" + field.getType() + ", 实际为" + value.getClass());
                }
                field.set(instance, value);
            }
        }
        return instance;
    }

    /**
     * 判断contactId是否为用户id
     * @param contactId
     * @return
     */
    public static boolean isUser(String contactId){
        UserContactTypeEnum prefix = UserContactTypeEnum.getPrefix(contactId);
        return prefix == UserContactTypeEnum.USER;
    }

    /**
     * 判断contactId是否为群id
     * @param contactId
     * @return
     */
    public static boolean isGroup(String contactId){
        UserContactTypeEnum prefix = UserContactTypeEnum.getPrefix(contactId);
        return prefix == UserContactTypeEnum.GROUP;
    }


}
